package com.jecs.tools;

import org.wlld.MatrixTools.Matrix;
import org.wlld.entity.SentenceModel;
import org.wlld.entity.WordTwoVectorModel;
import org.wlld.naturalLanguage.word.MyKeyWord;
import org.wlld.naturalLanguage.word.WordEmbedding;
import org.wlld.rnnNerveCenter.ModelParameter;
import org.wlld.rnnNerveCenter.RandomModel;
import org.wlld.rnnNerveCenter.RandomNerveManager;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.jecs.bean.BeanMangerOnly;
import com.jecs.config.Config;
import com.jecs.entity.KeyWordModelMapping;
import com.jecs.entity.MyWordModel;
import com.jecs.entity.Sentence;
import org.wlld.entity.KeyWordForSentence;
import org.wlld.naturalLanguage.languageCreator.CatchKeyWord;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

public class Tools {
    private void haveKeyWord(BeanMangerOnly beanMangerOnly, List<Sentence> sentences, boolean init) throws Exception {
        File file = new File(Config.onlyKeyWord); //创建文件
        MyKeyWord myKeyWord = beanMangerOnly.getMyKeyWord();
        if (!file.exists() || init) {//模型文件不存在重新学习
            List<KeyWordForSentence> keyWordForSentenceList = new ArrayList<>();
            for (Sentence sentence : sentences) {
                if (sentence.getWord() != null) {
                    KeyWordForSentence keyWordForSentence = new KeyWordForSentence();
                    keyWordForSentence.setSentence(sentence.getWord());
                    keyWordForSentence.setKeyWord(sentence.getNoun());//不存在关键词也是一种训练，因为该模型的目的是关键词敏感性嗅探
                    keyWordForSentenceList.add(keyWordForSentence);
                }
            }
            ModelParameter modelParameter = myKeyWord.study(keyWordForSentenceList);//学习完毕获取模型
            writeModel(JSONObject.toJSONString(modelParameter), Config.onlyKeyWord);
        } else {//模型文件存在直接读
            myKeyWord.insertModel(readModelParameter());
        }
    }

    private void keyWord(BeanMangerOnly beanMangerOnly, List<Sentence> sentences) throws IOException {//处理关键词
        File file = new File(Config.KeyWordModelUrl); //创建文件
        Map<Integer, CatchKeyWord> catchKeyWordMap = beanMangerOnly.catchKeyWord();
        if (!file.exists()) {//重新学习
            List<KeyWordModelMapping> keyWordModelMappings = new ArrayList<>();
            Map<Integer, List<Sentence>> sentenceMap = new HashMap<>();
            for (Sentence sentence : sentences) {
                int key = sentence.getSecond();//类别
                String word = sentence.getWord();
                String keyWord = sentence.getNoun();//关键词
                if (word != null && word.length() > 0 && keyWord != null && keyWord.length() > 0) {
                    if (sentenceMap.containsKey(key)) {
                        sentenceMap.get(key).add(sentence);
                    } else {
                        List<Sentence> sentenceList = new ArrayList<>();
                        sentenceList.add(sentence);
                        sentenceMap.put(key, sentenceList);
                    }
                }
            }
            for (Map.Entry<Integer, List<Sentence>> entry : sentenceMap.entrySet()) {
                List<Sentence> sentenceList = entry.getValue();
                int key = entry.getKey();
                List<KeyWordForSentence> keyWordForSentenceList = new ArrayList<>();
                CatchKeyWord catchKeyWord = new CatchKeyWord();
                catchKeyWordMap.put(key, catchKeyWord);//TODO 吃内存
                System.out.println("key:" + key);
                for (Sentence sentence : sentenceList) {
                    KeyWordForSentence keyWordForSentence = new KeyWordForSentence();
                    keyWordForSentence.setSentence(sentence.getWord());
                    keyWordForSentence.setKeyWord(sentence.getNoun());
                    keyWordForSentenceList.add(keyWordForSentence);
                }
                catchKeyWord.study(keyWordForSentenceList);//耗时的过程
                KeyWordModelMapping keyWordModelMapping = new KeyWordModelMapping();
                keyWordModelMapping.setKey(key);
                keyWordModelMapping.setKeyWordModel(catchKeyWord.getModel());
                keyWordModelMappings.add(keyWordModelMapping);
            }
            MyWordModel model = new MyWordModel();
            model.setKeyWordModelMappings(keyWordModelMappings);
            //模型写出
            writeModel(JSONObject.toJSONString(model), Config.KeyWordModelUrl);
        } else {//TODO 读取模型
            List<KeyWordModelMapping> keyWordModels = JSONObject.parseObject(readPaper(file), MyWordModel.class).getKeyWordModelMappings();
            for (KeyWordModelMapping keyWordModelMapping : keyWordModels) {
                int key = keyWordModelMapping.getKey();
                CatchKeyWord catchKeyWord = new CatchKeyWord();
                catchKeyWordMap.put(key, catchKeyWord);
                catchKeyWord.insertModel(keyWordModelMapping.getKeyWordModel());
            }
        }
    }

    public void initSemantics(BeanMangerOnly beanMangerOnly, List<Sentence> sentences) throws Exception {
        if (sentences != null && sentences.size() > 0) {
            sentences = anySort(sentences);//语句乱序 有助于样本均衡
        }
        boolean isStudy = initWordEmbedding(beanMangerOnly, sentences);//初始化词向量嵌入
        initSentenceModel(beanMangerOnly, sentences, isStudy);//初始化语言模型
        haveKeyWord(beanMangerOnly, sentences, isStudy);//关键词敏感性嗅探模型
        keyWord(beanMangerOnly, sentences);//关键词抓取
    }

    private void initSentenceModel(BeanMangerOnly beanMangerOnly, List<Sentence> sentences, boolean isStudy) throws Exception {//初始化语言模型
        File file = new File(Config.SentenceModelUrl); //创建文件
        if (!file.exists() || isStudy) {//模型文件不存在，或者需要强制初始化，则进行初始化
            Map<Integer, List<String>> model = new HashMap<>();//语义识别
            for (Sentence sentence : sentences) {
                int type = sentence.getSecond();
                if (type == 0) {
                    throw new Exception("type id Cannot be 0");
                }
                String word = sentence.getWord();
                if (model.containsKey(type)) {
                    model.get(type).add(word);
                } else {
                    List<String> words = new ArrayList<>();
                    words.add(word);
                    model.put(type, words);
                }
            }
            RandomNerveManager randomNerveManager = beanMangerOnly.getRandomNerveManager();
            randomNerveManager.init();//语言模型初始化
            RandomModel mySentenceModel = randomNerveManager.studyType(model);
            String sentenceModel = JSON.toJSONString(mySentenceModel);
            writeModel(sentenceModel, Config.SentenceModelUrl);
        } else {//直接读文件
            beanMangerOnly.getRandomNerveManager().insertModel(readSentenceModel());//初始化随机rnn网络集群
        }
    }

    private boolean initWordEmbedding(BeanMangerOnly beanMangerOnly, List<Sentence> sentences) throws Exception {//初始化词嵌入模型
        File file = new File(Config.Word2VecModelUrl); //创建文件
        WordEmbedding wordEmbedding = beanMangerOnly.getWordEmbedding();
        boolean isStudy = false;
        if (file.exists()) {//模型文件存在
            wordEmbedding.insertModel(readWord2VecModel());//初始化word2Vec编码器
        } else {//模型文件不存在
            isStudy = true;
            SentenceModel sentenceModel = new SentenceModel();
            for (Sentence sentence : sentences) {
                sentenceModel.setSentence(sentence.getWord());
            }
            wordEmbedding.init(sentenceModel);
            WordTwoVectorModel wordTwoVectorModel = wordEmbedding.start();//词向量开始学习
            String model = JSON.toJSONString(wordTwoVectorModel);
            writeModel(model, Config.Word2VecModelUrl);
        }
        return isStudy;
    }

    private List<Sentence> anySort(List<Sentence> sentences) {//做乱序
        Random random = new Random();
        List<Sentence> sent = new ArrayList<>();
        int time = sentences.size();
        for (int i = 0; i < time; i++) {
            int size = sentences.size();
            int index = random.nextInt(size);
            sent.add(sentences.get(index));
            sentences.remove(index);
        }
        return sent;
    }

    private RandomModel readSentenceModel() {
        File file = new File(Config.SentenceModelUrl);
        String a = readPaper(file);
        return JSONObject.parseObject(a, RandomModel.class);
    }

    private WordTwoVectorModel readWord2VecModel() {
        File file = new File(Config.Word2VecModelUrl);
        String a = readPaper(file);
        return JSONObject.parseObject(a, WordTwoVectorModel.class);
    }

    private ModelParameter readModelParameter() {
        File file = new File(Config.onlyKeyWord);
        String a = readPaper(file);
        return JSONObject.parseObject(a, ModelParameter.class);
    }

    private void writeModel(String model, String url) throws IOException {//写出模型与 激活参数
        OutputStreamWriter out = new OutputStreamWriter(Files.newOutputStream(Paths.get(url)), StandardCharsets.UTF_8);
        out.write(model);
        out.close();
    }

    private String readPaper(File file) {
        InputStream read = null;
        String context = null;
        try {
            read = Files.newInputStream(file.toPath());
            byte[] bt = new byte[read.available()];
            read.read(bt);
            context = new String(bt, StandardCharsets.UTF_8);
            read.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (read != null) {
                try {
                    read.close(); //确保关闭
                } catch (IOException el) {
                }
            }
        }
        return context;
    }
}
